package mq

import (
	"context"
	"encoding/json"
	"fmt"
	"log"

	"github.com/ammyhaber/seckill/pkg/mq"
	"github.com/google/uuid"
)

// InventoryMessageType 库存消息类型
type InventoryMessageType string

const (
	// InventoryMessageTypeLock 锁定库存
	InventoryMessageTypeLock InventoryMessageType = "LOCK_INVENTORY"
	// InventoryMessageTypeConfirm 确认扣减
	InventoryMessageTypeConfirm InventoryMessageType = "CONFIRM_INVENTORY"
	// InventoryMessageTypeCancel 取消扣减
	InventoryMessageTypeCancel InventoryMessageType = "CANCEL_INVENTORY"
)

// InventoryMessage 库存消息
type InventoryMessage struct {
	MessageID   string               `json:"message_id"`   // 消息ID
	MessageType InventoryMessageType `json:"message_type"` // 消息类型
	OrderID     string               `json:"order_id"`     // 订单ID
	ProductID   int64                `json:"product_id"`   // 商品ID
	Count       int                  `json:"count"`        // 数量
	UserID      int64                `json:"user_id"`      // 用户ID
}

// InventoryProducer 库存消息生产者
type InventoryProducer struct {
	rabbitMQ *mq.RabbitMQ
}

// NewInventoryProducer 创建库存消息生产者
func NewInventoryProducer(rabbitMQ *mq.RabbitMQ) *InventoryProducer {
	return &InventoryProducer{
		rabbitMQ: rabbitMQ,
	}
}

// Initialize 初始化消息队列配置
func (p *InventoryProducer) Initialize() error {
	// 声明交换机
	err := p.rabbitMQ.DeclareExchange("inventory_exchange", "direct")
	if err != nil {
		return err
	}

	// 声明队列
	err = p.rabbitMQ.DeclareQueue("inventory_queue")
	if err != nil {
		return err
	}

	// 绑定队列到交换机
	err = p.rabbitMQ.BindQueue("inventory_queue", "inventory_exchange", "inventory_key")
	if err != nil {
		return err
	}

	return nil
}

// SendLockInventoryMessage 发送锁定库存消息
func (p *InventoryProducer) SendLockInventoryMessage(ctx context.Context, orderID string, productID int64, count int, userID int64) error {
	// 生成消息ID
	messageID := uuid.New().String()

	// 创建消息
	message := &InventoryMessage{
		MessageID:   messageID,
		MessageType: InventoryMessageTypeLock,
		OrderID:     orderID,
		ProductID:   productID,
		Count:       count,
		UserID:      userID,
	}

	// 序列化消息
	body, err := json.Marshal(message)
	if err != nil {
		return fmt.Errorf("序列化消息失败: %w", err)
	}

	// 发送消息
	err = p.rabbitMQ.PublishWithContext(ctx, "inventory_exchange", "inventory_key", body)
	if err != nil {
		return fmt.Errorf("发送消息失败: %w", err)
	}

	log.Printf("发送锁定库存消息: %s, 订单ID: %s, 商品ID: %d\n", messageID, orderID, productID)
	return nil
}

// SendConfirmInventoryMessage 发送确认库存消息
func (p *InventoryProducer) SendConfirmInventoryMessage(ctx context.Context, orderID string, productID int64, count int, userID int64) error {
	// 生成消息ID
	messageID := uuid.New().String()

	// 创建消息
	message := &InventoryMessage{
		MessageID:   messageID,
		MessageType: InventoryMessageTypeConfirm,
		OrderID:     orderID,
		ProductID:   productID,
		Count:       count,
		UserID:      userID,
	}

	// 序列化消息
	body, err := json.Marshal(message)
	if err != nil {
		return fmt.Errorf("序列化消息失败: %w", err)
	}

	// 发送消息
	err = p.rabbitMQ.PublishWithContext(ctx, "inventory_exchange", "inventory_key", body)
	if err != nil {
		return fmt.Errorf("发送消息失败: %w", err)
	}

	log.Printf("发送确认库存消息: %s, 订单ID: %s, 商品ID: %d\n", messageID, orderID, productID)
	return nil
}

// SendCancelInventoryMessage 发送取消库存消息
func (p *InventoryProducer) SendCancelInventoryMessage(ctx context.Context, orderID string, productID int64, count int, userID int64) error {
	// 生成消息ID
	messageID := uuid.New().String()

	// 创建消息
	message := &InventoryMessage{
		MessageID:   messageID,
		MessageType: InventoryMessageTypeCancel,
		OrderID:     orderID,
		ProductID:   productID,
		Count:       count,
		UserID:      userID,
	}

	// 序列化消息
	body, err := json.Marshal(message)
	if err != nil {
		return fmt.Errorf("序列化消息失败: %w", err)
	}

	// 发送消息
	err = p.rabbitMQ.PublishWithContext(ctx, "inventory_exchange", "inventory_key", body)
	if err != nil {
		return fmt.Errorf("发送消息失败: %w", err)
	}

	log.Printf("发送取消库存消息: %s, 订单ID: %s, 商品ID: %d\n", messageID, orderID, productID)
	return nil
}
